perm filename CHGCLS.TEX[CLS,LSP] blob sn#833999 filedate 1987-02-05 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	"edsel!lgd"@navajo/su
C00019 ENDMK
CāŠ—;
"edsel!lgd"@navajo/su
Class Changing write-up
\begincom{change-class}\ftype{Function}

\label Purpose:

The function {\bf change-class} changes the class of an instance to a 
new class.  It destructively modifies and returns the instance.   The values
of slots held in common between the old and new class are preserved in
the new instance.   Any methods for {\bf class-changed} are run.    See Remarks
for details on these aspects of {\bf change-class}, and for a description 
of the restrictions on when {\bf change-class} can be used. 

\label Syntax:

\Defun {change-class} {instance new-class}

\label Arguments:

The {\it instance\/} argument is a Lisp object, although 
not all objects are required to allow {\bf change-class}.   See Remarks below. 

The {\it new-class\/} argument is a class object or a symbol that names
a class. 

\label Values:

The modified instance is returned.  The result of {\bf change-class}
is {\bf eq} to the {\it instance} argument.

\label Examples:

\screen!

(defclass position () ())

(defclass x-y-position (position)
  ((x :initform 0)
   (y :initform 0))
  (:accessor-prefix position-))

(defclass rho-theta-position (position)
  ((rho :initform 0)
   (theta :initform 0))
  (:accessor-prefix position-))

(defmethod class-changed ((old x-y-position) 
                          (new rho-theta-position))
  ;; Copy the position information from old to new to make new
  ;; be a rho-theta-position at the same position as old.
  (let ((x (position-x old))
        (y (position-y old)))
    (setf (position-rho new) (atan y x)
          (position-theta new) (sqrt (+ (* x x) (* y y))))))

\endscreen!

At this point an instance of the class {\tt x-y-position} can be changed
to be an instance of the class {\tt rho-theta-position} using {\bf
change-class}:

\screen!

(setq p1 (make-instance 'x-y-position :x 2 :y 0))

(change-class p1 'rho-theta-position)

\endscreen!

The result is that the instance bound to {\tt p1} is now of the class
{\tt rho-theta-position}.   The method for {\bf class-changed} performed
the initializion of the {\tt rho} and {\tt theta} slots
based on the value of the {\tt X} and {\tt Y} slots,
which were maintained by the old instance.   

\label Remarks:

The \CLOS\ guarantees that {\bf change-class} is allowed for the following
case only:  let $C\sub 1$ and $C\sub 2$ be classes that are defined by
{\bf defclass} without using the {\bf :metaclass} option in either case;
let $X$ be an instance of $C\sub 1$. Then the class of $X$ can be changed
from $C\sub 1$ to $C\sub 2$.  Both before and after the call to {\bf
change-class}, the metaclass of $X$ is the default metaclass, namely {\bf
standard-class}).

Whether {\bf change-class} is allowed for instances of a different
metaclass than the default one is up to the implementor of the
particular metaclass.  Also, whether {\bf change-class} is allowed to
change an object's metaclass is up to the implementors of the two
particular metaclasses.  The chapter on the meta-object protocol will
describe how to control this.

Implementators can choose to support {\bf change-class} in additional
cases if they desire.  For example, this standard does not require that
{\bf change-class} be able to accept an instance of a standard type class
as its first argument or a standard type class as its second argument;
however it is valid for an implementation to support it for some
standard type classes.

If {\bf change-class} is applied to arguments that are not supported by
the implementation, an error is signalled.

The function 
{\bf change-class} preserves the values of slots 
whose names are the same in both the old and new classes
and initializes any slots that are provided by 
the new class but not the old class.   This behavior is described in 
detail in the section ``Redefining Classes.''

After completing all other actions, {\bf change-class} invokes the generic
function {\bf class-changed}.  The generic function {\bf class-changed}
can be used to initialize new slots differently than {\bf make-instance},
or to copy information from a slot in the old instance to a
differently-named slot in the new instance.  There are two semantic
difficulties associated with {\bf change-class}.  

The function {\bf change-class} has several semantic difficulties. First,
it is a destructive operation that can be invoked
within a method on an instance that was used to select that method. When
multiple methods are involved because methods are being combined, the problem
could be compounded. Second, some implementations might use compiler
optimizations of slot access whose assumptions are violated when the
class of an instance is changed. 

This implies that an application programmer must not use {\bf
change-class} inside a method if any methods for that generic function 
access any slots. 

\label See Also:
 
``Redefining Classes''

{\bf class-changed}

\endcom

\begincom{class-changed}\ftype{Generic Function}

\label Purpose:

The generic function {\bf class-changed} is not intended to be called by
programmers.  Its intended use is for programmers to write methods on it.
The generic function \{bf class-changed} is invoked by {\bf change-class};
{\bf change-class} can be invoked explicitly by the user or automatically
by the system after {\bf defclass} has been used to redefine an existing
class.

\label Syntax:

\Defun {class-changed} {previous current}

\label Arguments:

When {\bf change-class} is invoked on an instance, a copy of that instance
is made; {\bf change-class} then destructively alters the original instance.
The first argument to {\bf class-changed}, {\it previous\/}, is that copy,
and the second argument, {\it current}, is the altered original instance.

The typical use of {\it previous\/} is to extract old slot values using
{\bf slot-value} or {\bf with-slots}, or by invoking an accessor generic
function.  Any function, generic or not, can receive the value of {\it
previous\/} as an argument; thus information about the value of {\it
previous\/} that is not directly stored in slots can be extracted.

\label Values:

In both cases where {\bf class-changed} is used, the returned value 
is ignored. 

\label Examples:

See the example in the description of {\bf change-class}.

\label Remarks:

The arguments to {\bf class-changed} are computed by {\bf change-class}.
The first argument is a copy of the argument to {\bf change-class}; this
argument has dynamic extent within {\bf change-class}, and, therefore, it
is an error to reference any part of it once {\bf change-class} returns.

The default method for {\bf class-changed} does nothing.
Methods on {\bf class-changed} can be defined
that initialize new slots 
differently from {\bf make-instance} or that copy information from a slot in
the old instance to a differently-named slot in the new instance.
In this way
{\bf class-changed} methods can alter the default behavior
of {\bf change-class} with respect to slot value preservation.
The default behavior is described in ``Redefining Classes.'' 

The generic function {\bf class-changed} uses standard method 
combination, so {\bf :before}, {\bf :after}, {\bf :around}, and
unqualified methods are allowed. 

\label See Also:

``Redefining Classes''

{\bf change-class}

\endcom